﻿// See https://aka.ms/new-console-template for more information
//状态模式
//状态模式（State Pattern）是一种行为型设计模式，他允许对象在其内部状态发生改变时改变其行为，使其看起来好像是修改了自己的类。
//在状态模式中，我们将对象的状态定义为一个独立的类，并使对象在其内部状态发生改变时切换到新的状态类。这样，当对象需要执行不同的行为时，我们只需要改变他的状态，而不需要改变对象本身的实现。
//状态模式是一种较为复杂的设计模式。用于解决系统中复杂对象的状态转换以及不同状态下的封装问题。当一个系统中的某个对象存在多个状态，这些状态之间可以进行转换，而且在对象在不同状态下会存在不同的行为时可以使用状态模式。
//在现实生活中水存在多种状态，它可以凝固成冰，也可以蒸发为水蒸气。在软件系统中，有些对象也会像水一样有多种状态，这些状态-在某种状态下可以相互转换，而对象在不同的状态下也会有不同的行为，一般我们可以使用复杂的分支语句来进行状态的判断和转换操作，但这会导致代码的可维护性和灵活性下降，特别是出现新的状态时，代码的扩展性也很差，客户端的代码也需要进行相应的修改，违背了开闭免原则，为了解决这个问题，我们可以使用状态模式。状态模式用于解决系统中复杂对象的状态转换以及不同状态下行为而得封装问题。

//状态模式通常包含一下角色：
//·Context（上下文/状态机）：它定义了客户端所使用的接口，并维护了一个指向具体状态对象的引用作为当前状态。
//·State（状态）：它定义了一个接口，用于封装上下文对象的特定状态相关的行为。
//·ConcreteState（具体状态）：它实现了State接口，并定义了该状态下的具体行为，每个状态的行为可能不一样，公共的行为可以定义在抽象状态里面。

Elevator elevator = new Elevator();
elevator.Open();
elevator.Close();
elevator.Run();
elevator.Open();



Console.WriteLine("Hello, World!");

//现在有一个电梯类，他又三种状态，开启，关闭和运行，根据不同的状态，他会有不同的行为。
//State状态接口
internal interface IState
{
    void Open();

    void Close();

    void Run();
}

//ConcreteSate关闭状态
internal class CloseState : IState
{
    public void Close()
    {
        Console.WriteLine("电梯门已经关闭");
    }

    public void Open()
    {
        Console.WriteLine("电梯门打开了");
    }

    public void Run()
    {
        Console.WriteLine("电梯开始运行");
    }
}

//开启状态
internal class OpenState : IState
{
    public void Close()
    {
        Console.WriteLine("电梯门关闭了");
    }

    public void Open()
    {
        Console.WriteLine("电梯门已经打开");
    }

    public void Run()
    {
        Console.WriteLine("电梯不能运行，门还没关");
    }
}

//运行状态
internal class RunState : IState
{
    public void Close()
    {
        Console.WriteLine("电梯门已经关闭");
    }

    public void Open()
    {
        Console.WriteLine("电梯门不能打开，电梯正在运行");
    }

    public void Run()
    {
        Console.WriteLine("电梯正在运行");
    }
}

//Context电梯类
class Elevator
{
    private IState _state;

    public Elevator()
    {
        //电梯默认为关闭状态A
        _state = new CloseState();
    }

    //设置电梯状态方法
    public void SetState(IState state)
    {
        this._state = state;
    }
    public void Open()
    {
        _state.Open();
        SetState(new OpenState());
    }
    public void Close()
    {
        _state.Close();
        SetState(new CloseState());
    }
    public void Run()
    {
        _state.Run();
        SetState(new RunState());
    }
}